#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
JSON File Analyzer Script
JSON文件分析脚本

功能：
1. 分析JSON格式的网络包数据
2. 识别网络异常和问题
3. 生成详细的分析报告
4. 为网页生成提供数据支持

作者：Falcomm自研团队
版本：1.0
日期：2025-08-15
"""

import sys
import json
import argparse
from pathlib import Path
from datetime import datetime
from collections import defaultdict, Counter

class JSONAnalyzer:
    def __init__(self):
        self.analysis_results = {}
        
    def analyze_json_file(self, json_file_path, output_dir):
        """分析JSON文件并生成分析结果"""
        json_file = Path(json_file_path)
        output_dir = Path(output_dir)
        
        if not json_file.exists():
            print(f"JSON file does not exist: {json_file}")
            return False
            
        if not output_dir.exists():
            output_dir.mkdir(parents=True, exist_ok=True)
        
        print(f"Starting JSON file analysis: {json_file.name}")
        
        try:
            # 读取JSON文件
            with open(json_file, 'r', encoding='utf-8') as f:
                data = json.load(f)
            
            # 执行分析
            analysis_results = self._perform_analysis(data)
            
            # 保存分析结果
            output_file = output_dir / f"{json_file.stem}_analysis.json"
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(analysis_results, f, ensure_ascii=False, indent=2)
            
            print(f"Analysis results saved successfully: {output_file}")
            
            return True
            
        except Exception as e:
            print(f"Error analyzing JSON file: {e}")
            import traceback
            traceback.print_exc()
            return False
    
    def _perform_analysis(self, data):
        """执行详细分析"""
        print("Performing network packet analysis...")
        
        analysis_results = {
            "metadata": {
                "analysis_timestamp": datetime.now().isoformat(),
                "analyzer_version": "1.0",
                "original_file": data.get("metadata", {}).get("filename", "unknown")
            },
            "summary": {},
            "anomalies": [],
            "flows": {},
            "statistics": {},
            "recommendations": []
        }
        
        # 基础统计
        packets = data.get("packets", [])
        analysis_results["summary"]["total_packets"] = len(packets)
        
        # 协议统计
        protocol_stats = self._analyze_protocols(packets)
        analysis_results["statistics"]["protocols"] = protocol_stats
        
        # 流量分析
        flows = self._analyze_flows(packets)
        analysis_results["flows"] = flows
        
        # 异常检测
        anomalies = self._detect_anomalies(packets, flows)
        analysis_results["anomalies"] = anomalies
        
        # 性能分析
        performance = self._analyze_performance(packets, flows)
        analysis_results["statistics"]["performance"] = performance
        
        # 生成建议
        recommendations = self._generate_recommendations(anomalies, performance)
        analysis_results["recommendations"] = recommendations
        
        return analysis_results
    
    def _analyze_protocols(self, packets):
        """分析协议分布"""
        protocol_counter = Counter()
        port_counter = Counter()
        
        for packet in packets:
            protocol = packet.get("protocol", "UNKNOWN")
            protocol_counter[protocol] += 1
            
            src_port = packet.get("src_port", 0)
            dst_port = packet.get("dst_port", 0)
            if src_port > 0:
                port_counter[f"src_{src_port}"] += 1
            if dst_port > 0:
                port_counter[f"dst_{dst_port}"] += 1
        
        return {
            "protocol_distribution": dict(protocol_counter),
            "top_ports": dict(port_counter.most_common(10))
        }
    
    def _analyze_flows(self, packets):
        """分析网络流"""
        flows = defaultdict(list)
        
        for packet in packets:
            # 创建流标识符
            if packet.get("src_ip") and packet.get("dst_ip"):
                # 使用源IP、目标IP、协议和端口创建流标识
                if packet.get("transport") == "TCP":
                    flow_key = f"TCP_{packet['src_ip']}:{packet.get('src_port', 0)}-{packet['dst_ip']}:{packet.get('dst_port', 0)}"
                elif packet.get("transport") == "UDP":
                    flow_key = f"UDP_{packet['src_ip']}:{packet.get('src_port', 0)}-{packet['dst_ip']}:{packet.get('dst_port', 0)}"
                else:
                    flow_key = f"OTHER_{packet['src_ip']}-{packet['dst_ip']}"
                
                flows[flow_key].append(packet)
        
        # 分析每个流
        flow_analysis = {}
        for flow_key, flow_packets in flows.items():
            flow_analysis[flow_key] = self._analyze_single_flow(flow_key, flow_packets)
        
        return flow_analysis
    
    def _analyze_single_flow(self, flow_key, packets):
        """分析单个流"""
        if not packets:
            return {}
        
        # 按时间排序
        sorted_packets = sorted(packets, key=lambda x: x.get("timestamp", 0))
        
        flow_info = {
            "packet_count": len(packets),
            "start_time": sorted_packets[0].get("timestamp", 0),
            "end_time": sorted_packets[-1].get("timestamp", 0),
            "duration": sorted_packets[-1].get("timestamp", 0) - sorted_packets[0].get("timestamp", 0),
            "total_bytes": sum(p.get("length", 0) for p in packets),
            "protocol": packets[0].get("protocol", "UNKNOWN"),
            "src_ip": packets[0].get("src_ip"),
            "dst_ip": packets[0].get("dst_ip"),
            "src_port": packets[0].get("src_port"),
            "dst_port": packets[0].get("dst_port"),
            "packets": packets  # 保存原始数据包信息
        }
        
        # TCP特定分析
        if flow_info["protocol"] == "TCP":
            tcp_analysis = self._analyze_tcp_flow(packets)
            flow_info["tcp_analysis"] = tcp_analysis
        
        # UDP特定分析
        elif flow_info["protocol"] == "UDP":
            udp_analysis = self._analyze_udp_flow(packets)
            flow_info["udp_analysis"] = udp_analysis
        
        return flow_info
    
    def _analyze_tcp_flow(self, packets):
        """分析TCP流"""
        syn_count = 0
        fin_count = 0
        rst_count = 0
        retransmissions = 0
        
        for packet in packets:
            flags = packet.get("tcp_flags", [])
            if "SYN" in flags:
                syn_count += 1
            if "FIN" in flags:
                fin_count += 1
            if "RST" in flags:
                rst_count += 1
        
        # 检测重传（简化版本）
        sequence_numbers = [p.get("sequence", 0) for p in packets if p.get("sequence")]
        if len(sequence_numbers) > len(set(sequence_numbers)):
            retransmissions = len(sequence_numbers) - len(set(sequence_numbers))
        
        return {
            "syn_count": syn_count,
            "fin_count": fin_count,
            "rst_count": rst_count,
            "retransmissions": retransmissions,
            "connection_status": self._determine_tcp_connection_status(syn_count, fin_count, rst_count)
        }
    
    def _analyze_udp_flow(self, packets):
        """分析UDP流"""
        return {
            "packet_count": len(packets),
            "is_dns": any(p.get("protocol") == "DNS" for p in packets)
        }
    
    def _determine_tcp_connection_status(self, syn_count, fin_count, rst_count):
        """确定TCP连接状态"""
        if syn_count == 0:
            return "NO_CONNECTION"
        elif fin_count == 0 and rst_count == 0:
            return "INCOMPLETE"
        elif rst_count > 0:
            return "RESET"
        elif fin_count > 0:
            return "COMPLETE"
        else:
            return "UNKNOWN"
    
    def _detect_anomalies(self, packets, flows):
        """检测网络异常"""
        anomalies = []
        
        # 检测TCP连接异常
        for flow_key, flow_info in flows.items():
            if flow_info.get("protocol") == "TCP":
                tcp_analysis = flow_info.get("tcp_analysis", {})
                
                # 检测未完成的连接
                if tcp_analysis.get("connection_status") == "INCOMPLETE":
                    anomalies.append({
                        "type": "TCP_CONNECTION_INCOMPLETE",
                        "severity": "HIGH",
                        "flow": flow_key,
                        "description": "TCP connection incomplete, potential connectivity issues",
                        "details": tcp_analysis
                    })
                
                # 检测重传
                if tcp_analysis.get("retransmissions", 0) > 0:
                    anomalies.append({
                        "type": "TCP_RETRANSMISSION",
                        "severity": "MEDIUM",
                        "flow": flow_key,
                        "description": f"Detected {tcp_analysis['retransmissions']} TCP retransmission packets",
                        "details": tcp_analysis
                    })
        
        # 检测端口扫描
        port_scan = self._detect_port_scan(packets)
        if port_scan:
            anomalies.append(port_scan)
        
        # 检测异常流量
        traffic_anomalies = self._detect_traffic_anomalies(packets)
        anomalies.extend(traffic_anomalies)
        
        return anomalies
    
    def _detect_port_scan(self, packets):
        """检测端口扫描"""
        src_ips = defaultdict(set)
        
        for packet in packets:
            src_ip = packet.get("src_ip")
            dst_port = packet.get("dst_port")
            if src_ip and dst_port:
                src_ips[src_ip].add(dst_port)
        
        # 检测单个IP访问大量端口
        for src_ip, ports in src_ips.items():
            if len(ports) > 10:  # 阈值可调整
                return {
                    "type": "PORT_SCAN",
                    "severity": "MEDIUM",
                    "source_ip": src_ip,
                    "description": f"Detected port scan from {src_ip}, accessed {len(ports)} ports",
                    "ports": list(ports)
                }
        
        return None
    
    def _detect_traffic_anomalies(self, packets):
        """检测流量异常"""
        anomalies = []
        
        # 检测大量小包（可能的DDoS）
        small_packets = [p for p in packets if p.get("length", 0) < 100]
        if len(small_packets) > len(packets) * 0.8:
            anomalies.append({
                "type": "SMALL_PACKET_FLOOD",
                "severity": "HIGH",
                "description": "Detected large number of small packets, potential DDoS attack",
                "percentage": len(small_packets) / len(packets) * 100
            })
        
        return anomalies
    
    def _analyze_performance(self, packets, flows):
        """分析网络性能"""
        if not packets:
            return {}
        
        timestamps = [p.get("timestamp", 0) for p in packets if p.get("timestamp")]
        if not timestamps:
            return {}
        
        # 计算时间间隔
        intervals = []
        for i in range(1, len(timestamps)):
            interval = timestamps[i] - timestamps[i-1]
            if interval > 0:
                intervals.append(interval)
        
        if not intervals:
            return {}
        
        return {
            "total_duration": max(timestamps) - min(timestamps),
            "average_interval": sum(intervals) / len(intervals),
            "min_interval": min(intervals),
            "max_interval": max(intervals),
            "packet_rate": len(packets) / (max(timestamps) - min(timestamps)) if max(timestamps) - min(timestamps) > 0 else 0
        }
    
    def _generate_recommendations(self, anomalies, performance):
        """生成处理建议"""
        recommendations = []
        
        # 基于异常生成建议
        for anomaly in anomalies:
            if anomaly["type"] == "TCP_CONNECTION_INCOMPLETE":
                recommendations.append({
                    "priority": "HIGH",
                    "category": "CONNECTIVITY",
                    "title": "Check TCP Connection Issues",
                    "description": "Incomplete TCP connections detected, recommend checking network connectivity and firewall configuration",
                    "actions": [
                        "Check target server status",
                        "Verify firewall rules",
                        "Check network routing"
                    ]
                })
            
            elif anomaly["type"] == "TCP_RETRANSMISSION":
                recommendations.append({
                    "priority": "MEDIUM",
                    "category": "PERFORMANCE",
                    "title": "Optimize TCP Transmission",
                    "description": "TCP retransmissions detected, recommend optimizing network configuration",
                    "actions": [
                        "Check network congestion",
                        "Adjust TCP timeout parameters",
                        "Optimize network bandwidth"
                    ]
                })
        
        # 基于性能生成建议
        if performance:
            if performance.get("packet_rate", 0) > 1000:  # 高包率
                recommendations.append({
                    "priority": "MEDIUM",
                    "category": "PERFORMANCE",
                    "title": "Monitor Network Performance",
                    "description": "High packet rate detected, recommend monitoring network performance",
                    "actions": [
                        "Deploy network monitoring tools",
                        "Set performance alerts",
                        "Regular performance assessment"
                    ]
                })
        
        return recommendations

def main():
    """主函数"""
    parser = argparse.ArgumentParser(description="JSON File Analyzer Tool")
    parser.add_argument("json_file", help="Input JSON file path")
    parser.add_argument("output_dir", help="Output analysis results directory")
    
    args = parser.parse_args()
    
    # 创建分析器实例
    analyzer = JSONAnalyzer()
    
    # 分析JSON文件
    success = analyzer.analyze_json_file(args.json_file, args.output_dir)
    
    if success:
        print("JSON analysis completed!")
        sys.exit(0)
    else:
        print("JSON analysis failed!")
        sys.exit(1)

if __name__ == "__main__":
    main() 